﻿namespace FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment
{
    using FiftyOne.Foundation.Mobile.Detection.Wurfl;
    using FiftyOne.Foundation.Mobile.Detection.Wurfl.Handlers;
    using FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers;
    using System;
    using System.Threading;

    internal class Matcher : FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Matcher
    {
        internal static FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Results Match(string userAgent, SegmentHandler handler)
        {
            if (handler.UserAgents.Count > 0)
            {
                if (Environment.ProcessorCount > 1)
                {
                    return MatchMultiProcessor(userAgent, handler);
                }
                return MatchSingleProcessor(userAgent, handler);
            }
            return null;
        }

        private static FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Results MatchMultiProcessor(string userAgent, SegmentHandler handler)
        {
            AutoResetEvent completeEvent = new AutoResetEvent(false);
            FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Request state = new FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Request(userAgent, handler, completeEvent);
            if (state.Count > 0)
            {
                for (int i = 0; i < Environment.ProcessorCount; i++)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Matcher.ServiceRequest), state);
                }
                while (!completeEvent.WaitOne(1, false))
                {
                }
            }
            return state.Results;
        }

        private static FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Results MatchSingleProcessor(string userAgent, SegmentHandler handler)
        {
            FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Request request = new FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Request(userAgent, handler);
            ServiceRequest(request);
            return request.Results;
        }

        private static void ServiceRequest(FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Request request)
        {
            DeviceInfo device = request.Next();
            while (device != null)
            {
                Segments segments = request.Handler.CreateSegments(device.UserAgent);
                int num2 = request.Target.Count - segments.Count;
                int index = 0;
                while (index < num2)
                {
                    segments.Add(new FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Segment(string.Empty));
                    index++;
                }
                for (index = 0; index < request.Target.Count; index++)
                {
                    int segmentWeight = request.Handler.GetSegmentWeight(index, request.Target.Count);
                    if (request.Target[index].Value == segments[index].Value)
                    {
                        segments[index].Score = 0;
                    }
                    else
                    {
                        segments[index].Score = Algorithms.EditDistance(request.Target[index].Value, segments[index].Value, 0x7fffffff) * segmentWeight;
                    }
                }
                int totalScore = segments.TotalScore;
                if (totalScore <= request.Results.LowestScore)
                {
                    lock (request.Results)
                    {
                        if (totalScore == request.Results.LowestScore)
                        {
                            request.Results.Add(device);
                        }
                        else if (totalScore < request.Results.LowestScore)
                        {
                            request.Results.LowestScore = totalScore;
                            request.Results.Clear();
                            request.Results.Add(device);
                        }
                    }
                }
                device = request.Next();
                request.Complete();
            }
        }

        private static void ServiceRequest(object sender)
        {
            ServiceRequest((FiftyOne.Foundation.Mobile.Detection.Wurfl.Matchers.Segment.Request) sender);
        }
    }
}

